package com.ruoyi.web.controller.gd;

import java.io.*;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.util.List;
import java.util.Arrays;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.amazonaws.util.IOUtils;
import lombok.RequiredArgsConstructor;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.gd.fj.domain.vo.ZFujianVo;
import com.ruoyi.gd.fj.domain.bo.ZFujianBo;
import com.ruoyi.gd.fj.service.IZFujianService;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;
import com.aspose.cells.SaveFormat;
import com.aspose.cells.Workbook;

import static com.ruoyi.web.controller.utils.LicenseData.getLicense;

/**
 * 附件
 *
 * @author ruoyi
 * @date 2024-03-17
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/gd/fj")
@Slf4j
public class ZFujianController extends BaseController {

    private final IZFujianService iZFujianService;

    @Value("${upload.path}")
    private String uploadPath;

    @Autowired
    private IZFujianService fujianService;

    /**
     * 查询附件列表
     */
    @GetMapping("/list")
    public TableDataInfo<ZFujianVo> list(ZFujianBo bo, PageQuery pageQuery) {
        return iZFujianService.queryPageList(bo, pageQuery);
    }

    /**
     * 查询附件列表
     */
    @GetMapping("/all/list/{ids}")
    public List<ZFujianVo> allList(@PathVariable String ids) {
        ZFujianBo zFujianBo = new ZFujianBo();
        zFujianBo.setFjid(ids);
        return iZFujianService.queryList(zFujianBo);
    }

    /**
     * 导出附件列表
     */
    @Log(title = "附件", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(ZFujianBo bo, HttpServletResponse response) {
        List<ZFujianVo> list = iZFujianService.queryList(bo);
        ExcelUtil.exportExcel(list, "附件", ZFujianVo.class, response);
    }

    /**
     * 获取附件详细信息
     *
     * @param fjid 主键
     */
    @GetMapping("/{fjid}")
    public R<ZFujianVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable String fjid) {
        return R.ok(iZFujianService.queryById(fjid));
    }

    /**
     * 新增附件
     */
    @Log(title = "附件", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody ZFujianBo bo) {
        return toAjax(iZFujianService.insertByBo(bo));
    }

    /**
     * 修改附件
     */
    @Log(title = "附件", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ZFujianBo bo) {
        return toAjax(iZFujianService.updateByBo(bo));
    }

    /**
     * 删除附件
     *
     * @param fjids 主键串
     */
    @Log(title = "附件", businessType = BusinessType.DELETE)
    @DeleteMapping("/{fjids}")
    public R<Void> remove(@PathVariable String[] fjids) {
        return toAjax(iZFujianService.deleteWithValidByIds(Arrays.asList(fjids), true));
    }

    @PostMapping("/file/upload")
    public ResponseEntity<Object> upload(@RequestParam("file") MultipartFile file) throws Exception {
        if (file.isEmpty()) {
            return ResponseEntity.badRequest().body("File is empty.");
        }
        // 获取文件原名
        String originalFilename = file.getOriginalFilename();
        // 判断当前地址是否存在，不存在则创建
        Path filePath = Paths.get(uploadPath);
        // 判断路径是否存在
        if (!Files.exists(filePath)) {
            // 如果路径不存在，则尝试创建目录（假设uploadPath是指向目录的）
            Files.createDirectories(filePath);
        }
        // 获取后缀
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        // 重新生成文件名
        String fileName = IdUtil.simpleUUID() + suffix;
        LocalDate currentDate = LocalDate.now();
        // 分别获取年、月、日
        int year = currentDate.getYear();
        int monthValue = currentDate.getMonthValue();
        int dayOfMonth = currentDate.getDayOfMonth();
        // 生成Excel路径
        String suffixPath = "/" + year + "/" + monthValue + "/" + dayOfMonth + "/";
        // 判断当前文件路径的文件夹是否存在，不存在则创建
        if (!Files.exists(Paths.get(uploadPath + suffixPath))) {
            // 路径不存在，尝试创建
            try {
                Files.createDirectories(Paths.get(uploadPath + suffixPath));
            } catch (Exception e) {
                System.err.println("创建目录时出错: " + e.getMessage());
                log.info("==============================================================");
                log.info("路径创建失败----> "+ uploadPath + suffixPath );
                log.info("==============================================================");
            }
        }
        // 构建新的文件名和目标路径
        Path targetLocation = Paths.get(uploadPath + suffixPath + fileName);
        // 将文件保存到指定目录
        Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
        // 上传后将文件数据添加到文件数据库
        ZFujianBo fujianBo = new ZFujianBo();
        fujianBo.setFjid(IdUtil.simpleUUID());  //设置附件id
        fujianBo.setFjname(originalFilename);   //设置附件名称
        fujianBo.setFjpath(suffixPath + fileName);  //设置附件路径
        fujianBo.setFjtype(suffix);
        fujianService.insertByBo(fujianBo);

        JSONObject entries = new JSONObject();
        // 判断当前上传的文件是不是excel，如果是的话需要转版
        if (suffix.contains("xls") || suffix.contains("xlsx")) {
            // 将上传的附件转换为pdf
            // 验证License
            if (!getLicense()) {
                new RuntimeException("license验证失败！");
            }
            String pdfFileName = IdUtil.simpleUUID() + ".pdf";
            String pdfPath = uploadPath + suffixPath + pdfFileName;
            Workbook wb = new Workbook(uploadPath + suffixPath + fileName);// 原始excel路径
            File pdfFile = new File(pdfPath);// 输出路径
            FileOutputStream fileOS = new FileOutputStream(pdfFile);
            wb.save(fileOS, SaveFormat.PDF);
            String fjPdfName = originalFilename.substring(0, originalFilename.lastIndexOf("."));
            ZFujianBo fujian = new ZFujianBo();
            fujian.setFjid(IdUtil.simpleUUID());  //设置附件id
            fujian.setFjname(fjPdfName + ".pdf");   //设置附件名称
            fujian.setFjpath(suffixPath + pdfFileName);  //设置附件路径
            fujian.setFjtype(".pdf");
            fujianService.insertByBo(fujian);

            entries.put("fjname", originalFilename);  // excel附件名称
            entries.put("fjpdfname", fujian.getFjname());  // pdf附件名称
            entries.put("fj", fujianBo.getFjid());  // excel附件id
            entries.put("fjpdf", fujian.getFjid()); // pdf附件id
            entries.put("fjpath", fujianBo.getFjpath());
            entries.put("fjpdfpath", fujian.getFjpath());

            if (fileOS != null) {
                fileOS.close();
            }
        }else {
            // 否则就是其他类型的附件上传
            entries.put("fjname", originalFilename);
            entries.put("fj", fujianBo.getFjid());
            entries.put("fjpath", fujianBo.getFjpath());
        }

        return ResponseEntity.ok(entries);
    }

    /**
     * 获取附件详细信息
     *
     */
    @GetMapping(value = "/getFj/{id}")
    public byte[] getPdf(@PathVariable String id) throws IOException {
        log.info("==============================================================");
        log.info("==============================================================");
        log.info("获取当前附件的id: "+ id);
        log.info("==============================================================");
        log.info("==============================================================");
        // 从文件或其他数据源获取PDF文件流
        // 1.通过id获取当前附件信息
        ZFujianVo fujianVo = iZFujianService.queryById(id);
        // 2.获取附件路径
        String path = uploadPath + fujianVo.getFjpath();
        log.info("==============================================================");
        log.info("==============================================================");
        log.info("获取当前附件的路径: " + path);
        log.info("==============================================================");
        log.info("==============================================================");
        // 3.获取文件
        File file = new File(path);
        FileInputStream inputStream = new FileInputStream(file);
        return IOUtils.toByteArray(inputStream);
    }

    @GetMapping("/download/{id}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String id) {
        try {
            // 1.通过id获取当前附件信息
            ZFujianVo fujianVo = iZFujianService.queryById(id);
            // 2.获取附件路径
            String path = uploadPath + fujianVo.getFjpath();
            Path filePath = Paths.get(path);
            Resource resource = new UrlResource(filePath.toUri());
            if (resource.exists() && resource.isReadable()) {
                return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                    .body(resource);
            } else {
                throw new RuntimeException("Could not read the file!");
            }
        } catch (MalformedURLException e) {
            throw new RuntimeException("Error: " + e.getMessage());
        }
    }

    @PostMapping("/file/batchUpload")
    public ResponseEntity<Object> batchUpload(@RequestParam("files") List<MultipartFile> fileArr) throws Exception {
        JSONArray array = new JSONArray();
        // 遍历附件
        for (MultipartFile file : fileArr) {
            if (file.isEmpty()) {
                return ResponseEntity.badRequest().body("File is empty.");
            }
            // 获取文件原名
            String originalFilename = file.getOriginalFilename();
            // 判断当前地址是否存在，不存在则创建
            Path filePath = Paths.get(uploadPath);
            // 判断路径是否存在
            if (!Files.exists(filePath)) {
                // 如果路径不存在，则尝试创建目录（假设uploadPath是指向目录的）
                Files.createDirectories(filePath);
            }
            // 获取后缀
            String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
            // 重新生成文件名
            String fileName = IdUtil.simpleUUID() + suffix;
            LocalDate currentDate = LocalDate.now();
            // 分别获取年、月、日
            int year = currentDate.getYear();
            int monthValue = currentDate.getMonthValue();
            int dayOfMonth = currentDate.getDayOfMonth();
            // 生成Excel路径
            String suffixPath = "/" + year + "/" + monthValue + "/" + dayOfMonth + "/";
            // 判断当前文件路径的文件夹是否存在，不存在则创建
            if (!Files.exists(Paths.get(uploadPath + suffixPath))) {
                // 路径不存在，尝试创建
                try {
                    Files.createDirectories(Paths.get(uploadPath + suffixPath));
                } catch (Exception e) {
                    System.err.println("创建目录时出错: " + e.getMessage());
                    log.info("==============================================================");
                    log.info("路径创建失败----> "+ uploadPath + suffixPath );
                    log.info("==============================================================");
                }
            }
            // 构建新的文件名和目标路径
            Path targetLocation = Paths.get(uploadPath + suffixPath + fileName);
            // 将文件保存到指定目录
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
            // 上传后将文件数据添加到文件数据库
            ZFujianBo fujianBo = new ZFujianBo();
            fujianBo.setFjid(IdUtil.simpleUUID());  //设置附件id
            fujianBo.setFjname(originalFilename);   //设置附件名称
            fujianBo.setFjpath(suffixPath + fileName);  //设置附件路径
            fujianBo.setFjtype(suffix);
            fujianService.insertByBo(fujianBo);

            // 否则就是其他类型的附件上传
            JSONObject entries = new JSONObject();
            entries.put("fjname", originalFilename);
            entries.put("fj", fujianBo.getFjid());
            entries.put("fjpath", fujianBo.getFjpath());
            array.add(entries);
        }

        return ResponseEntity.ok(array);
    }


}
